package com.timguan.render.service.service;

import com.timguan.render.api.api.B2CMallServiceReturnCode;
import com.timguan.render.api.api.backend.CMSRouteService;
import com.timguan.render.api.entity.cms.CMSPage;
import com.timguan.render.api.entity.cms.CMSRoute;
import com.timguan.render.dao.domain.cms.CmsRouteDO;
import com.timguan.render.dao.domain.cms.CmsRouteDOExample;
import com.timguan.render.dao.domain.cms.CmsSpecialPageDO;
import com.timguan.render.dao.domain.cms.CmsTopicDO;
import com.timguan.render.dao.manager.cms.CmsRouteManagerImpl;
import com.timguan.render.dao.manager.cms.CmsSpecialPageManagerImpl;
import com.timguan.render.dao.manager.cms.CmsTopicManagerImpl;
import com.timguan.render.dataprocessor.processor.Constants;
import com.timguan.render.dataprocessor.processor.URLHelper;
import com.timguan.render.service.common.B2CMallConstants;
import net.pocrd.entity.ServiceException;
import net.pocrd.entity.ServiceRuntimeException;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * Created by guankaiqiang on 2015/3/22.
 */
public class CMSRouteServiceImpl implements CMSRouteService {
    @Autowired
    private CmsRouteManagerImpl cmsRouteManagerImpl;
    @Autowired
    private CmsTopicManagerImpl cmsTopicManagerImpl;
    @Autowired
    private CmsSpecialPageManagerImpl cmsSpecialPageManagerImpl;

    /**
     * @param accessPlatform
     * @param srcUri
     * @param srcActivityId
     * @param appId
     * @param appVersion
     * @throws ServiceException
     */
    @Override
    public CMSPage getCmsPage(AccessPlatform accessPlatform, String srcUri, int srcActivityId, int appId, String appVersion)
            throws ServiceException {
        CMSRoute route = getRoute(srcUri, srcActivityId, appId, appVersion, null);
        return getRoutedCmsPage(accessPlatform, srcUri, srcActivityId, appId, route);
    }

    /**
     * @param accessPlatform
     * @param srcUri
     * @param srcActivityId
     * @param appId
     * @param appVersion
     * @throws ServiceException
     */
    @Override
    public CMSPage getCmsPage(AccessPlatform accessPlatform, String srcUri, int srcActivityId, int appId, String appVersion,
                              String group) throws ServiceException {
        CMSRoute route = getRoute(srcUri, srcActivityId, appId, appVersion, group);
        return getRoutedCmsPage(accessPlatform, srcUri, srcActivityId, appId, route);
    }

    /**
     * 专题的路由信息
     *
     * @param accessPlatform
     * @param srcUri
     * @param srcActivityId
     * @param appId
     * @param route
     * @throws ServiceException
     */
    private CMSPage getRoutedCmsPage(AccessPlatform accessPlatform, String srcUri, int srcActivityId, int appId,
                                     CMSRoute route) throws ServiceException {
        CMSPage result = null;
        if (route != null) {
            if (accessPlatform == AccessPlatform.APP_APIGW) {
                if (route.getTargetPageType() == B2CMallConstants.APP_PAGE_TYPE) {
                    //页面被路由到APP页面
                    result = new CMSPage(route.getTargetPageId(), B2CMallConstants.APP_PAGE_TYPE);
                } else {
                    //接口访问的专题被路由到了非APP页面，需要重定向
                    result = new CMSPage(route.getTargetPageId(), route.getTargetPageType(), false, true,
                            URLHelper.getUrl(route.getSrcActivityType(), srcUri, srcActivityId));
                }
            } else if (accessPlatform == AccessPlatform.H5_RENDER) {
                if (route.getTargetPageType() == B2CMallConstants.H5_PAGE_TYPE) {
                    //页面路由到h5页面
                    result = new CMSPage(route.getTargetPageId(), B2CMallConstants.H5_PAGE_TYPE);
                } else if (route.getTargetPageType() == B2CMallConstants.APP_PAGE_TYPE) {
                    //页面路由到app页面
                    if (appId == B2CMallConstants.B2C_IOS_APPID || appId == B2CMallConstants.B2C_ANDROID_APPID) {
                        //app环境中 页面路由到另一个app页面 invoke redirect
                        result = new CMSPage(route.getTargetPageId(), route.getTargetPageType(), false, true,
                                URLHelper.getUrl(B2CMallConstants.APP_PAGE_TYPE, srcUri, srcActivityId));
                    } else {
                        //H5环境中 阻止native路由规则生效,以H5方式打开APP
                        result = new CMSPage(route.getTargetPageId(), route.getTargetPageType());
                    }
                } else {
                    //H5不支持向PC跳转
                    result = new CMSPage(route.getTargetPageId(), route.getTargetPageType(), true, false, Constants.H5_BASE_URL);
                }
            } else if (accessPlatform == AccessPlatform.PC_RENDER) {
                if (route.getTargetPageType() == B2CMallConstants.PC_PAGE_TYPE) {
                    //pc上页面路由到另一个PC页面
                    result = new CMSPage(route.getTargetPageId(), route.getTargetPageType());
                } else {
                    if (route.getSrcActivityType() == B2CMallConstants.PC_PAGE_TYPE) {
                        //PC环境 阻止PC路由H5规则生效，规则在H5打开才生效
                        result = new CMSPage(route.getTargetPageId(), route.getTargetPageType());
                    } else {
                        //禁止PC向其他端的跳转
                        result = null;
                    }
                }
            }
        } else {
            if (accessPlatform == AccessPlatform.APP_APIGW) {
                //app访问必须通过路由
                result = new CMSPage(null, null, false, true,
                        URLHelper.getUrl(B2CMallConstants.APP_PAGE_TYPE, srcUri, srcActivityId));
            } else {
                int type = appId == B2CMallConstants.B2C_PC_APPID ? B2CMallConstants.PC_PAGE_TYPE :
                        appId == B2CMallConstants.B2C_H5_APPID ? B2CMallConstants.H5_PAGE_TYPE : B2CMallConstants.APP_PAGE_TYPE;
                int pageId = getPageId(srcUri, srcActivityId, type);
                result = new CMSPage(pageId, type);
            }
        }
        return result;
    }

    private static final String APP_VERSION_SPLIT = "\\.";

    /**
     * 版本号解析为数字版本号
     *
     * @param version
     */

    private static long parseAppVersion(String version) {
        String[] appVersion = version.split(APP_VERSION_SPLIT);
        long hv = 0, mv = 0, lv = 0;
        if (appVersion.length == 1) {
            hv = StringUtils.isNumeric(appVersion[0]) ? Long.parseLong(appVersion[0]) : 0;
        }
        if (appVersion.length == 2) {
            hv = StringUtils.isNumeric(appVersion[0]) ? Long.parseLong(appVersion[0]) : 0;
            mv = StringUtils.isNumeric(appVersion[1]) ? Long.parseLong(appVersion[1]) : 0;
        }
        if (appVersion.length == 3) {
            hv = StringUtils.isNumeric(appVersion[0]) ? Long.parseLong(appVersion[0]) : 0;
            mv = StringUtils.isNumeric(appVersion[1]) ? Long.parseLong(appVersion[1]) : 0;
            lv = StringUtils.isNumeric(appVersion[2]) ? Long.parseLong(appVersion[2]) : 0;
        }
        return hv * 1000000000 + mv * 1000000 + lv * 1000;
    }

    /**
     * 版本号比较
     *
     * @param v1
     * @param v2
     */
    public static int compareAppVersion(String v1, String v2) {
        long dv1 = 0, dv2 = 0;
        if (StringUtils.isNotBlank(v1)) {
            dv1 = parseAppVersion(v1);
        }
        if (StringUtils.isNotBlank(v2)) {
            dv2 = parseAppVersion(v2);
        }
        if (dv1 == dv2) {
            return 0;
        } else if (dv1 > dv2) {
            return 1;
        } else {
            return -1;
        }
    }

    /**
     * 版本号降序排序
     */
    static class AppVersionComparator implements Comparator<CmsRouteDO> {
        @Override
        public int compare(CmsRouteDO o1, CmsRouteDO o2) {
            return -1 * compareAppVersion(o1.getAppVersion(), o2.getAppVersion());
        }

    }

    private static final AppVersionComparator APP_VERSION_COMPARATOR = new AppVersionComparator();

    /**
     * 查找页面路由信息
     *
     * @param srcUri
     * @param srcActivityId
     * @param appId
     * @param appVersion
     */
    public CMSRoute getRoute(String srcUri, int srcActivityId, int appId, String appVersion, String groupName) {
        CmsRouteDO cmsRouteDO = null;
        CmsRouteDOExample condition = new CmsRouteDOExample();
        CmsRouteDOExample.Criteria criteria = condition.createCriteria();
        criteria.andIsDeleteEqualTo(0);
        if (srcActivityId > 0) {
            criteria.andSrcActivityIdEqualTo(srcActivityId);
        } else {
            criteria.andSrcUriEqualTo(srcUri);
        }
        //仅对app生效
        if (appId != 0) {
            criteria.andAppIdEqualTo(appId);
        }
        List<CmsRouteDO> cmsRouteDOList = cmsRouteManagerImpl.selectByExample(condition);
        if (cmsRouteDOList == null || cmsRouteDOList.size() == 0) {
            return null;
        }
        if (appId == B2CMallConstants.B2C_ANDROID_APPID || appId == B2CMallConstants.B2C_IOS_APPID) {
            //版本号降序排序
            Collections.sort(cmsRouteDOList, APP_VERSION_COMPARATOR);
            /**
             * 1.groupName为空，只要找到小于等于appVersion，并且是最靠近的那条数据就OK
             * 2.groupName不为空，要找到等于APPVersion，并且groupName相同的那条数据，如果不存在，则按照步骤1来
             */
            boolean isNotEmpty = StringUtils.isNotBlank(groupName);
            CmsRouteDO temp = null;
            for (CmsRouteDO element : cmsRouteDOList) {
                //不考虑groupName选出一个最合适的一条数据，做备用
                if (cmsRouteDO == null && compareAppVersion(appVersion, element.getAppVersion()) >= 0) {
                    cmsRouteDO = element;
                    if (!isNotEmpty) {
                        break;
                    }
                }
                if (isNotEmpty && groupName.equals(element.getGroupName())) {
                    if (compareAppVersion(appVersion, element.getAppVersion()) > 0) {
                        break;
                    } else if (appVersion.equals(element.getAppVersion())) {
                        temp = element;
                        break;
                    }
                }
            }
            //处理groupName没有匹配上，就选不考虑groupName的最合适的一条
            if (isNotEmpty && temp != null) {
                cmsRouteDO = temp;
            }
        } else {
            cmsRouteDO = cmsRouteDOList.get(0);
        }
        //查找最佳匹配的分组数据
        CMSRoute cmsRoute = null;
        if (cmsRouteDO != null) {
            cmsRoute = new CMSRoute();
            cmsRoute.setSrcUri(cmsRouteDO.getSrcUri());
            cmsRoute.setSrcActivityId(cmsRouteDO.getSrcActivityId() != null ? cmsRouteDO.getSrcActivityId() : 0);
            cmsRoute.setSrcActivityType(cmsRouteDO.getSrcActivityType());
            cmsRoute.setTargetPageId(cmsRouteDO.getTargetPageId());
            cmsRoute.setTargetPageType(cmsRouteDO.getTargetPageType());
        }
        return cmsRoute;
    }

    public int getPageId(String uri, int activityId, int type) {
        if (activityId != 0) {
            CmsTopicDO cmsTopicDO = cmsTopicManagerImpl.selectByPrimaryKey(activityId);
            if (cmsTopicDO != null) {
                return cmsTopicDO.getPageId();
            }
        } else {
            CmsSpecialPageDO cmsSpecialPageDO = cmsSpecialPageManagerImpl.getCmsSpecialPageByUri(uri, type);
            if (cmsSpecialPageDO != null) {
                return cmsSpecialPageDO.getPageId();
            }
        }
        throw new ServiceRuntimeException(B2CMallServiceReturnCode.TOPIC_NOT_FOUND, "页面不存在");
    }
}
